/**
 * 
 */
package org.shark.jdbcTemplateTool.utils;

import com.google.common.collect.Maps;
import org.shark.jdbcTemplateTool.dao.BaseDao;
import org.shark.jdbcTemplateTool.dao.config.SqlCommand;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * @author lenovo
 * @description
 * @date 2016年8月25日
 */
public class SqlCommandUtil {

	/**
	 * 
	 */
	private static Map<Method, SqlCommand> mapSc = Maps.newConcurrentMap();

	private static Map<String, BaseDao> mapDao = Maps.newConcurrentMap();

	/**
	 * @param className
	 * @throws ClassNotFoundException
	 */
	public static void initSqlCommandByClass(String className) throws ClassNotFoundException {
		Class<?> cls = Class.forName(className);

		// 本类方法
		for (Method m : cls.getDeclaredMethods()) {
			if (!mapSc.containsKey(m)) {
				String key = className + "." + m.getName();
				SqlCommand sc = new SqlCommand();
				sc.setMethod(m);
				sc.setKey(key);
				sc.setMethodName(m.getName());
				sc.setAdd(isSqlMethod(m.getName(), SqlCommand.INSERT));
				sc.setUpdate(isSqlMethod(m.getName(), SqlCommand.UPDATE));
				sc.setDelete(isSqlMethod(m.getName(), SqlCommand.DELETE));
				Class<?> returnClass = m.getReturnType();
				if (returnClass.isArray()) {
					// 数组
					sc.setArray(true);
				} else if (List.class.isAssignableFrom(returnClass)) {
					// 返回List
					sc.setList(true);
				} else if (Map.class.isAssignableFrom(returnClass)) {
					// 返回Map
					sc.setMap(true);
				} else {
					sc.setReturnClass(returnClass);
				}
				Type returnType = m.getGenericReturnType();
				if (returnType instanceof ParameterizedType) {
					ParameterizedType t = (ParameterizedType) returnType;
					Type[] types = t.getActualTypeArguments();
					sc.setReturnClass(types[0].getClass());
				}
				mapSc.put(m, sc);
			}
		}

		// 继承了BaseDao
		if (cls.getInterfaces() != null) {
			int index = 0;
			Class<?>[] interfaces = cls.getInterfaces();
			for (Class<?> c : interfaces)  {
				if (c.getName().equals(BaseDao.class.getName())) {
					break;
				}
				index ++;
			}
			Type superClass = cls.getGenericInterfaces()[index];
			ParameterizedType p = (ParameterizedType) superClass;
			Class<?> c1 = (Class<?>)p.getActualTypeArguments()[0];
			Type pk = p.getActualTypeArguments()[1];

			for (Method m : cls.getMethods()) {
				// 基类方法
				if (!mapSc.containsKey(m)) {
					String key = className + "." + m.getName();
					SqlCommand sc = new SqlCommand();
					sc.setMethod(m);
					sc.setMethodName(m.getName());
					sc.setEntityClass(c1);
					sc.setSuperMethod(true);
					mapSc.put(m, sc);
				}
			}
		}
	}

	public static SqlCommand getSqlCommand(Method m) {
		return mapSc.get(m);
	}

	/**
	 * @param methodName
	 * @param prefix
	 * @return
	 */
	private static boolean isSqlMethod(String methodName, String[] prefix) {
		for (String s : prefix) {
			if (methodName.startsWith(s)) {
				return true;
			}
		}
		return false;
	}
}
